/**
 * Copyright 2007-2010 非也
 * All rights reserved. 
 * 
 * This library is free software; you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License v3 as published by the Free Software
 * Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License along
 * with this library; if not, see http://www.gnu.org/licenses/lgpl.html.
 *
 */
package org.fireflow2.designer.eclipse.modelwrapper;

import java.util.List;

import org.eclipse.draw2d.geometry.Rectangle;
import org.fireflow.model.ModelElement;
import org.fireflow.pdl.fpdl20.diagram.DiagramElement;
import org.fireflow.pdl.fpdl20.diagram.basic.Circle;
import org.fireflow.pdl.fpdl20.diagram.basic.Shape;
import org.fireflow.pdl.fpdl20.diagram.basic.impl.PointImpl;
import org.fireflow.pdl.fpdl20.process.Activity;
import org.fireflow.pdl.fpdl20.process.EndNode;
import org.fireflow.pdl.fpdl20.process.Router;
import org.fireflow.pdl.fpdl20.process.StartNode;
import org.fireflow.pdl.fpdl20.process.SubProcess;
import org.fireflow.pdl.fpdl20.process.Transition;
import org.fireflow.pdl.fpdl20.process.WorkflowProcess;
import org.fireflow2.designer.eclipse.modelwrapper.basic.EndNodeWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.RouterWrapper;
import org.fireflow2.designer.eclipse.modelwrapper.basic.StartNodeWrapper;

/**
 *
 * @author 非也 nychen2000@163.com
 * Fire Workflow 官方网站：www.firesoa.com 或者 www.fireflow.org
 *
 */
public abstract class ModelWrapper extends AbsWrapper{
	ModelElement wfElement = null;//流程元素
	DiagramElement diagramElement = null;//对应的图形元素
	
	public ModelWrapper(ModelElement arg0,DiagramElement diagramElement) {
		this.wfElement = arg0;
		this.diagramElement = diagramElement;
	}
	
	public ModelElement getWorkflowModelElement() {
		return this.wfElement;
	}
	
	public DiagramElement getDiagramElement(){
		return this.diagramElement;
	}

	public void setName(String name) {
		String oldName = null;
		String newName = name;
		if (newName == null)
			newName = "";
		if (this.wfElement != null){
			oldName = this.wfElement.getName();
			if (oldName == null)
				oldName = "";
			if (oldName.equals(newName)) {
				return;
			}
			
			this.wfElement.setName(newName.trim());
			
			//修改DiagramElement的WorkflowElementRef值
			if (diagramElement!=null){
				diagramElement.setWorkflowElementRef(wfElement.getId());
			}
		}else{
			//修改DiagramElement的Title
			Shape shape = diagramElement.getShape();
			oldName = shape.getTitle();
			if (oldName==null) oldName = "";
			if (oldName.equals(newName)){
				return;
			}
			
			shape.setTitle(newName);
		}
		this.firePropertyChange(NAME, oldName, newName.trim());
	}
	
	

	public String getSn() {
		if (this.diagramElement == null){
			return this.wfElement.getId();
		}
		return this.diagramElement.getId();
	}

	public String getID() {
		if (this.wfElement == null)
			return this.diagramElement.getId();
		return this.wfElement.getId();
	}

	public String getName() {
		if (this.wfElement == null){
			return this.diagramElement.getShape().getTitle();
		}else{
			return this.wfElement.getName();
		}		
	}

	public void setDisplayName(String arg0) {
		String old  = null;
		String newName = arg0;
		if (newName == null)
			newName = "";
		
		if (this.wfElement != null){
			old = this.wfElement.getDisplayName();
			if (old == null)
				old = "";

			if (old.equals(newName.trim())) {
				return;
			}
			this.wfElement.setDisplayName(newName.trim());
		}else{
			Shape shape = this.getDiagramElement().getShape();
			old = shape.getTitle();
			if (old == null)
				old = "";

			if (old.equals(newName.trim())) {
				return;
			}
			shape.setTitle(newName);
		}

		this.firePropertyChange(NAME, old, newName.trim());
	}

	public String getDisplayName() {
		if (this.wfElement == null){
			return this.diagramElement.getShape().getTitle();
		}else{
			return this.wfElement.getDisplayName();
		}
		
	}

	public void setDescription(String arg0) {
		String old = null;
		String newDesc = arg0;
		if (newDesc == null)
			newDesc = "";
		if (this.wfElement != null){
			old = this.wfElement.getDescription();
			if (old == null)
				old = "";

			if (old.equals(newDesc.trim())) {
				return;
			}
			this.wfElement.setDescription(newDesc);
		}else{
			Shape shape = this.diagramElement.getShape();
			old = shape.getContent();
			if (old == null)
				old = "";

			if (old.equals(newDesc.trim())) {
				return;
			}
			shape.setContent(newDesc);
		}

		
		this.firePropertyChange(NAME, old, arg0);
	}

	
	public String getDescription() {
		if (this.wfElement == null){
			Shape shape = this.diagramElement.getShape();
			return  shape.getContent();
		}else{
			return this.wfElement.getDescription();
		}

	}



	
	/**
	 * 检查name是否有同名冲突
	 * @return
	 */
	public boolean isTheNameConflict(String newName){
		boolean conflict = false;
		Wrapper parent = this.getParent();
		if (parent==null) return false;
		ModelElement parentWFElement = ((ModelWrapper)this.getParent()).getWorkflowModelElement();
		
		if (parentWFElement==null) return false;
		
		if (parentWFElement instanceof WorkflowProcess){
			WorkflowProcess process = (WorkflowProcess)parentWFElement;
			List<SubProcess> subflows = process.getLocalSubProcesses();
			for (SubProcess sbflow : subflows){
				if (sbflow.getName().equals(newName)){
					conflict = true;
				}
			}
			
		}else if (parentWFElement instanceof SubProcess){	
			SubProcess process = (SubProcess)parentWFElement;
			List<StartNode> startNodes = process.getStartNodes();
			for (StartNode startNode : startNodes){
				if (startNode.getName().equalsIgnoreCase(newName)){
					conflict = true;
					break;
				}
			}

			
			List<Activity> activities = process.getActivities();
	
			for (int i=0;!conflict && i<activities.size();i++){
				Activity activity = (Activity)activities.get(i);
				if (activity.getName().equalsIgnoreCase(newName)){
					conflict = true;
					break;
				}
			}
			
			List<Router> synchronizers = process.getRouters();
			for (int i=0;!conflict && i<synchronizers.size();i++){
				Router synchronizer = (Router)synchronizers.get(i);
				if (synchronizer.getName().equalsIgnoreCase(newName)){
					conflict = true;
					break;					
				}
			}
			
			List<EndNode> endNodes = process.getEndNodes();
			for (int i=0;!conflict && i<endNodes.size();i++){
				EndNode endNode = (EndNode)endNodes.get(i);
				if (endNode.getName().equalsIgnoreCase(newName)){
					conflict = true;
					break;					
				}
			}	
					
			
			List<Transition> transitions = process.getTransitions();
			for (int i=0;!conflict && i<transitions.size();i++){
				Transition transition = (Transition)transitions.get(i);
				if (transition.getName().equalsIgnoreCase(newName)){
					conflict = true;
					break;					
				}
			}		
				
		}
		
		return conflict;
	}
	
	/**
	 * 将新的位置信息转化到model中保存起来
	 * @param rect
	 */
	public void setBox(Rectangle rect){
		//开始节点，结束节点，Router只可以改变位置，不可以改变大小
		if (this instanceof StartNodeWrapper ||
				this instanceof EndNodeWrapper || 
				this instanceof RouterWrapper){
			Rectangle oldRect = this.getBox();
			if ((oldRect.x == rect.x && oldRect.y == rect.y) ||
					(oldRect.x+oldRect.width == rect.x+rect.width && oldRect.y+oldRect.height == rect.y+rect.height)){
				return;
			}
			
			if (this instanceof StartNodeWrapper ||
				this instanceof EndNodeWrapper ){
				PointImpl theCenter = null;
				if (rect.width>0){
					theCenter = new PointImpl(rect.x+rect.width/2,rect.y+rect.height/2);
				}else{
					theCenter = new PointImpl(rect.x,rect.y);
				}
				((Circle)diagramElement.getShape()).setTheCenter(theCenter);
			}
			else if (this instanceof RouterWrapper){
				PointImpl theCenter = null;
				if (rect.width>0){
					theCenter = new PointImpl(rect.x+rect.width/2,rect.y+rect.height/2);
				}else{
					theCenter = new PointImpl(rect.x,rect.y);
				}
				
				((org.fireflow.pdl.fpdl20.diagram.basic.Rectangle)diagramElement.getShape())
					.getBounds().setUpperLeftCorner(new PointImpl(theCenter.getX()-16,theCenter.getY()-16));
			}
		}
		else {
			if (!(this instanceof ConnectorWrapper)) {
				org.fireflow.pdl.fpdl20.diagram.basic.Rectangle fireRect = (org.fireflow.pdl.fpdl20.diagram.basic.Rectangle) diagramElement
						.getShape();
				fireRect.getBounds().setWidth(rect.width);
				fireRect.getBounds().setHeight(rect.height);
				fireRect.getBounds().getUpperLeftCorner().setX(rect.x);
				fireRect.getBounds().getUpperLeftCorner().setY(rect.y);
			}
		}
	
		this.firePropertyChange(LOCATION, null, rect);
	}
	
	/**
	 * 将保存在Model中的位置信息转换为Rectangle，采用的是相对坐标
	 * @return
	 */
    public Rectangle getBox(){
    	if (this.diagramElement!=null){
    		Shape shape = diagramElement.getShape();
    		if (shape instanceof org.fireflow.pdl.fpdl20.diagram.basic.Rectangle){
    			org.fireflow.pdl.fpdl20.diagram.basic.Rectangle fireRect = (org.fireflow.pdl.fpdl20.diagram.basic.Rectangle)shape;
    			if (fireRect==null || fireRect.getBounds()==null || fireRect.getBounds().getUpperLeftCorner()==null) return null;
    			
    			org.eclipse.draw2d.geometry.Rectangle rect = new org.eclipse.draw2d.geometry.Rectangle();
    			rect.x = fireRect.getBounds().getUpperLeftCorner().getX();
    			rect.y = fireRect.getBounds().getUpperLeftCorner().getY();
    			rect.width = fireRect.getBounds().getWidth();
    			rect.height = fireRect.getBounds().getHeight();
    			
    			return rect;
    		}else if (shape instanceof Circle){
    			
    			Circle circle = (Circle)diagramElement.getShape();
    			Rectangle rect = new Rectangle();
    			rect.setLocation(circle.getTheCenter().getX()-circle.getRadius(), circle.getTheCenter().getY()-circle.getRadius());
    			rect.setSize(circle.getRadius()*2,circle.getRadius()*2);
    			return rect;
    		}else{
    			return null;
    		}
    		
    		
    	}else{
    		return null;
    	}
    	
    }

	@Override
	public int hashCode() {
		if (this.diagramElement!=null){
			return diagramElement.getId().hashCode();
		}
		return super.hashCode();
	}
    
    
}
